#pragma once

#include <boost/algorithm/string.hpp>
#include <fstream>
#include <iostream>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
// #include "log.hpp"
#include "cppjieba/Jieba.hpp"

namespace ns_util {
  class FileUtil
  {
  public:
    static bool ReadFile(const std::string &file_path, std::string *out) 
    {
        std::ifstream in(file_path, std::ios::in);
        if (!in.is_open()) 
        {
          std::cerr << "open file " << file_path << " error " << std::endl;
          return false;
        }

        std::string line;//返回值？--std::istream&，当读取成功时，返回一个表示流状态的对象，
        while (std::getline(in, line)) //该对象会隐式转换为 true
        {
          *out += line;
        }
        in.close();
        return true;
    }
  };
  class StringUtil 
  {
    public:
      static void Split(const std::string &target, std::vector<std::string> *out,
                        const std::string &sep) {
        boost::split(*out, target, boost::is_any_of(sep), boost::token_compress_on);
  //token_compress_on选项指示在分割过程中，如果出现连续的分隔符，则将其视为一个分隔符，并且在结果中不会包含空字符串
      }
  };
//主要的词典文件，包含词汇和对应的词频，用于确定词的边界
  const char *const DICT_PATH = "./dict/jieba.dict.utf8";
//隐马尔可夫模型（HMM），用于处理未知词（在词典中不存在的词），提高分词的准确性。
  const char *const HMM_PATH = "./dict/hmm_model.utf8";
//用户自定义词典，用户可以在此文件中添加特定的词汇，以提高分词的适应性。
  const char *const USER_DICT_PATH = "./dict/user.dict.utf8";
//逆文档频率文件，用于计算词的重要性，有助于在某些任务中改善结果（如文本分类）。
  const char *const IDF_PATH = "./dict/idf.utf8";
//停用词文件，包含在文本处理中应该被忽略的常用词（如“的”、“是”等），以减少冗余。
  const char *const STOP_WORD_PATH = "./dict/stop_words.utf8";

  class JiebaUtil {
  private:
      // static cppjieba::Jieba jiebautil;
      cppjieba::Jieba jiebautil;
      std::unordered_map<std::string, bool> stop_words; //?去暂停词
  private:
      JiebaUtil()
          : jiebautil(DICT_PATH, HMM_PATH, USER_DICT_PATH, IDF_PATH, STOP_WORD_PATH) {}
      JiebaUtil(const JiebaUtil &) = delete; //?为什么你没这种意识--创建单例

    static JiebaUtil *instance;
  public:
  static JiebaUtil* get_instance()
  {
      static std::mutex mtx;
      if(instance==nullptr)
      {
        mtx.lock();
        if(instance==nullptr)
        {
          instance = new JiebaUtil();
          instance->InitJiebaUtil();
        }
        mtx.unlock();  
      }
      return instance;
  }
    void InitJiebaUtil()
    {
        std::ifstream in(STOP_WORD_PATH);
        if(!in.is_open())
        {
            //  LOG(FATAL, "load stop words file error");
                return;
        }
        std::string line;
        while(std::getline(in,line))
        {
            stop_words.insert({line,true});
        }
        in.close();
    }
    // std::vector<std::string>tmp;
    void CutForStringHelper(const std::string &src,std::vector<std::string> *out)
    {
        jiebautil.CutForSearch(src, *out);
        out->erase(std::remove_if(out->begin(), out->end(),
        [&](const std::string& word) {
            return stop_words.find(word) != stop_words.end();
        }), out->end());
        // for(auto iter = out->begin();iter<out->end();)
        // {
        //     auto pos = stop_words.find(*iter);
        //     if(pos != stop_words.end())
        //     {
        //       iter = out->erase(iter);
        //     }
        //     else
        //     {
        //       ++iter;
        //     }
        // }
    }
  public:

    static void CutForString(const std::string &src,std::vector<std::string> *out) 
    {
      ns_util::JiebaUtil::get_instance()->CutForStringHelper(src,out);
      // jiebautil.CutForSearch(content, *out);
      // limonp.Join(tmp.begin,tmp.end());
      // ouut->push_back()std::move
    }
  };
// cppjieba::Jieba JiebaUtil::jiebautil(DICT_PATH, HMM_PATH, USER_DICT_PATH,
//                                      IDF_PATH, STOP_WORD_PATH);
JiebaUtil *JiebaUtil::instance=nullptr;
}

/*
加上去除暂停词代码是，程序运行十分缓慢
std::remove_if 返回的新结束迭代器指向了新排列后有效元素的末尾，
实际上不需要的元素仍然在容器中，但它们被认为是无效的。为了真正删除这些元素，需要调用 erase 方法。
*/